import net from 'net';
import fs from 'fs';
import path from 'path';
import os from 'os';
import { fork } from 'child_process';
import { fileURLToPath } from 'url';
import { PORT, SEGMENT_FRAMES, OUTPUT_DIR, SAMPLE_RATE, CHANNELS, BIT_DEPTH } from './config.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 确保输出目录存在
const absoluteOutputDir = path.resolve(OUTPUT_DIR);
if (!fs.existsSync(absoluteOutputDir)) {
    fs.mkdirSync(absoluteOutputDir, { recursive: true });
    console.log('创建输出目录:', absoluteOutputDir);
}

// 子进程：专门写 OPUS，避免主进程阻塞
const workerPath = path.join(__dirname, 'opus_worker.js');
const worker = fork(workerPath, [], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'] });
let workerReady = false;
let workerExited = false;
let isShuttingDown = false;

worker.on('message', (msg) => {
    if (!msg || typeof msg !== 'object') return;
    if (msg.type === 'ready') workerReady = true;
    if (msg.type === 'error') console.error('写入子进程错误:', msg.message);
    if (msg.type === 'exited') workerExited = true;
});

worker.on('exit', (code, signal) => {
    workerExited = true;
    if (code !== 0) console.error('写入子进程异常退出:', code, signal || '');
});

worker.on('error', (err) => {
    workerExited = true;
    console.error('写入子进程进程错误:', err?.message || err);
});

worker.send({
    type: 'init',
    config: {
        sampleRate: SAMPLE_RATE,
        channels: CHANNELS,
        bitDepth: BIT_DEPTH,
        outputDir: absoluteOutputDir,
    },
});

const sockets = new Set();
let fileSeq = 0;

const server = net.createServer((socket) => {
    console.log('TCP 客户端已连接:', `${socket.remoteAddress}:${socket.remotePort}`);
    sockets.add(socket);

    let buf = Buffer.alloc(0);
    const frames = [];
    let frameCount = 0;
    let total = 0;

    // 设备信息（首包 JSON 行，以 '\n' 结束）
    let deviceInfoParsed = false;
    let device = { deviceId: 'unknown', clientId: 'unknown' };
    const safe = (s) => String(s ?? 'unknown').replace(/[^a-zA-Z0-9_-]/g, '-');

    function flush(final = false) {
        if (frames.length === 0) return;
        const name = `${safe(device.deviceId)}_${safe(device.clientId)}_${Date.now()}_${++fileSeq}.opus`;
        if (isShuttingDown || workerExited || !worker?.connected) {
            console.warn('子进程不可用，丢弃分片');
            frames.length = 0;
            frameCount = 0;
            return;
        }
        try {
            const framesToSave = frames.splice(0);
            worker.send({ type: 'opus_segment', frames: framesToSave, name });
            console.log(`已保存OPUS文件: ${name}, 帧数: ${framesToSave.length}`);
        } catch (e) {
            console.error('发送到子进程失败:', e?.message || e);
        }
        frameCount = 0;
    }

    function processBuffer() {
        let offset = 0;

        // 先解析设备信息（首行 JSON）
        if (!deviceInfoParsed) {
            const nl = buf.indexOf(0x0A); // '\n'
            if (nl === -1) return; // 等待更多数据
            const line = buf.slice(0, nl).toString('utf8').trim();
            offset = nl + 1;
            try {
                const obj = JSON.parse(line);
                // 支持ESP32发送的mac和chipid格式
                if (obj.mac && obj.chipid) {
                    device = {
                        deviceId: obj.chipid || 'unknown',
                        clientId: obj.mac || 'unknown',
                    };
                } else {
                    // 兼容原有格式
                    device = {
                        deviceId: obj.deviceId || obj.device_id || obj.id || 'unknown',
                        clientId: obj.clientId || obj.client_id || 'unknown',
                    };
                }
                console.log('设备信息:', device);
                console.log('MAC地址:', obj.mac || 'unknown');
                console.log('芯片ID:', obj.chipid || 'unknown');
                
                // 发送握手确认响应
                socket.write('ok\n');
                console.log('已发送握手确认: ok');
            } catch (e) {
                console.warn('设备信息解析失败，使用默认:', e?.message || e);
                // 即使解析失败也发送ok，避免客户端超时
                socket.write('ok\n');
                console.log('解析失败，但仍发送握手确认: ok');
            }
            deviceInfoParsed = true;
        }

        // 处理OPUS帧数据
        // 简化方法：假设每个TCP包包含一个完整的OPUS帧
        // 由于TCP是流式传输，我们需要等待足够的数据
        if (buf.length - offset > 0) {
            // 检查是否有合理的OPUS帧数据
            const frameData = buf.subarray(offset);
            
            // 验证第一个字节是否是合理的TOC字节
            if (frameData.length > 0) {
                const toc = frameData[0];
                const config = (toc >> 3) & 0x1F;
                const stereo = (toc >> 2) & 0x01;
                const frameType = toc & 0x3;
                
                // 检查是否是合理的OPUS帧（config 5对应60ms帧，config 11对应180ms帧）
                if ((config === 5 || config === 11) && frameData.length >= 10) { // 至少10字节的合理OPUS帧
                    frames.push(frameData);
                    frameCount++;
                    console.log(`收到OPUS帧 ${frameCount}: ${frameData.length} 字节 (config: ${config}, frameType: ${frameType}, stereo: ${stereo})`);
                    
                    // 按帧数分片：每SEGMENT_FRAMES帧保存一个文件
                    if (frameCount >= SEGMENT_FRAMES) {
                        flush();
                    }
                } else {
                    console.log(`跳过无效OPUS帧: ${frameData.length} 字节 (config: ${config}, frameType: ${frameType})`);
                }
            }
        }
        
        // 清空缓冲区，等待下一个TCP包
        buf = Buffer.alloc(0);
        
        // 保留未处理的数据
        if (offset < buf.length) {
            buf = buf.subarray(offset);
        } else {
            buf = Buffer.alloc(0);
        }
    }

    // 提供给优雅停止时调用的上下文方法
    socket._ctx = {
        getPendingBytes: () => buf.length,
        writeAllPending: () => flush(true),
    };

    let index = 0;

    socket.on('data', (chunk) => {
        index++;
        if (index % 50 === 0) {
            console.log('receive data', total);
        }
        buf = Buffer.concat([buf, chunk]);
        total += chunk.length;
        processBuffer();
    });

    socket.on('end', () => {
        console.log('TCP 客户端已断开, 总字节:', total);
        processBuffer();
        flush(true);
    });

    socket.on('close', () => {
        sockets.delete(socket);
    });

    socket.on('error', (err) => {
        console.error('TCP 连接错误:', err?.message || err);
    });
});

server.listen(PORT, () => {
    console.log(`TCP 服务器已启动，监听端口 ${PORT}`);
    console.log('分片帧数=', SEGMENT_FRAMES);
    const nets = os.networkInterfaces();
    const addrs = [];
    for (const name of Object.keys(nets)) {
        for (const n of nets[name] || []) {
            if (n && n.family === 'IPv4' && !n.internal) addrs.push(n.address);
        }
    }
    if (addrs.length === 0) {
        console.log(`可用地址: 127.0.0.1:${PORT}`);
    } else {
        console.log('可用地址:');
        for (const a of addrs) console.log(`  ${a}:${PORT}`);
    }
});

process.on('SIGINT', () => {
    console.log('\n正在停止 TCP 服务器...');
    isShuttingDown = true;
    // 先停止接受新连接
    try { server.close(); } catch { }

    // 先把每个连接的剩余缓存写出
    for (const s of sockets) {
        const ctx = s && s._ctx;
        if (ctx && ctx.getPendingBytes && ctx.writeAllPending) {
            try { ctx.writeAllPending(); } catch { }
        }
    }

    // 然后销毁连接，避免继续读取
    for (const s of sockets) {
        try { s.destroy(); } catch { }
    }

    // 通知子进程退出（在它写完队列后会发 exited）
    if (!workerExited && worker?.connected) {
        try { worker.send({ type: 'exit' }); } catch { }
    }

    // 等待子进程退出或兜底超时
    const timeout = setTimeout(() => process.exit(0), 5000);
    timeout.unref();
    const check = setInterval(() => {
        if (workerExited) {
            clearInterval(check);
            clearTimeout(timeout);
            process.exit(0);
        }
    }, 100);
    check.unref();
});